#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

typedef unsigned long long int Fib_Number;
// Used for two-item arrays storing the last two Fibonacci numbers
typedef Fib_Number *Fib_Iterator;

static char *ERR_MSG = "";
static bool ERR_OCCURRED = false;

#define FATAL_ERR_CHECK() if (ERR_OCCURRED) {fprintf(stderr, "%s\n", ERR_MSG); \
			exit(EXIT_FAILURE);}

static void
set_error(const char *msg)
{
	ERR_MSG = (char *)msg;
	ERR_OCCURRED = true;
}

Fib_Iterator
Fib_new(void)
{
	// Rely on fact that calloc() zero's out new memory
	Fib_Iterator new_iter = (Fib_Iterator) calloc(2, sizeof(Fib_Number));
	if (!new_iter) {
		set_error("Fib_new(): calloc() failed");
		return NULL;
	}

	new_iter[0] = 1;

	return new_iter;
}

Fib_Number
Fib_next(Fib_Iterator iter_index)
{
	assert(iter_index);

	unsigned int to_return = iter_index[1];
	unsigned int fib = iter_index[0] + iter_index[1];
	iter_index[1] = iter_index[0];
	iter_index[0] = fib;
	return to_return;
}

void
Fib_free(Fib_Iterator iter_index)
{
	free(iter_index);
}



int
main(int argc, char *argv[])
{
	Fib_Iterator fib_iter = Fib_new();
	FATAL_ERR_CHECK();

	unsigned int count = atoi(argv[1]) + 1;

	for (int x = 0; x < count; x += 1) {
		Fib_Number fib = Fib_next(fib_iter);
		FATAL_ERR_CHECK();

		printf("%lld ", fib);
	}
	Fib_free(fib_iter);
	printf("...\n");
	return 0;
}
